package com.example.elysiumease.controller;


import com.example.elysiumease.encoder.SHA256PasswordEncoder;
import com.example.elysiumease.exception.BusinessException;
import com.example.elysiumease.mapper.UserMapper;
import com.example.elysiumease.model.User;
import com.example.elysiumease.result.ResponseResult;
import com.example.elysiumease.service.CustomUserDetails;
import com.example.elysiumease.service.EmailService;
import com.example.elysiumease.util.JwtTokenUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;


// AuthController.java
@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private EmailService emailService;

    @PostMapping("/register")
    public ResponseResult<?> register(@Valid @RequestBody RegisterRequest request) {
        if (userMapper.selectByUsername(request.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }

        User user = new User();
        user.setUsername(request.getUsername());
        user.setPasswordHash(passwordEncoder.encode(request.getPassword()));
        user.setAngelName(request.getAngelName());
        user.setRole(User.Role.OPERATOR); // 默认角色

        userMapper.insert(user);

        String registerMsg = String.format(
                "新用户注册通知\n\n" +
                        "用户名: %s\n" +
                        "天使名称: %s\n" +
                        "注册时间: %s",
                request.getUsername(),
                request.getAngelName(),
                new Date().toString()
        );
        emailService.sendNotificationEmail("新用户注册通知", registerMsg);

        return ResponseResult.success("注册成功");
    }

    @PostMapping("/login")
    public ResponseResult<Map<String, String>> login(@Valid @RequestBody LoginRequest request) {
        try {
            // 1. 加载用户认证信息
            UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());

            // 2. 类型安全验证
            if (!(userDetails instanceof CustomUserDetails)) {
                throw new AuthenticationServiceException("用户凭证格式异常");
            }
            CustomUserDetails customDetails = (CustomUserDetails) userDetails;

            // 3. 密码验证
            if (!passwordEncoder.matches(request.getPassword(), customDetails.getPassword())) {
                throw new BadCredentialsException("密码验证失败");
            }

            // 4. 获取完整用户对象
            User authenticatedUser = customDetails.getUser();

            // 5. 生成JWT令牌
            String token = jwtTokenUtil.generateToken(authenticatedUser);

            // 6. 存储到Redis（带过期时间）
            redisTemplate.opsForValue().set(
                    "AUTH:" + authenticatedUser.getUsername(),
                    token,
                    jwtTokenUtil.getExpiration(),
                    TimeUnit.MILLISECONDS
            );

            String loginMsg = String.format(
                    "用户登录通知\n\n" +
                            "用户名: %s\n" +
                            "登录时间: %s\n" +
                            "IP地址: %s", // 可选：添加IP地址
                    authenticatedUser.getUsername(),
                    new Date().toString(),
                    getClientIP() // 需要实现获取客户端IP的方法
            );
            emailService.sendNotificationEmail("用户登录通知", loginMsg);
            // 7. 返回标准化响应
            return ResponseResult.success(Collections.singletonMap("token", token));

        } catch (UsernameNotFoundException e) {
            throw new BusinessException(401,"用户不存在");
        } catch (BadCredentialsException e) {
            throw new BusinessException(401,"凭证无效");
        } catch (Exception e) {
            throw new BusinessException(500,"登录失败：" + e.getMessage());
        }
    }



    private String getClientIP() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    // DTO定义
    @Data
    public static class RegisterRequest {
        @NotBlank private String username;
        @NotBlank private String password;
        @NotBlank private String angelName;
    }

    @Data
    public static class LoginRequest {
        @NotBlank private String username;
        @NotBlank private String password;
    }



}